package scene;


// EyeCamera.java
// Andrew Davison, ad@fivedots.coe.psu.ac.th, June 2007

/* The camera creates an asymmetric frustum, with the camera
   offset to the left or right depending on if the instance
   is for the left or right eye. The viewport for the camera
   is also stored here.
*/

import java.awt.event.*;

import javax.media.opengl.*;
import javax.media.opengl.glu.*;


public class EyeCamera
{
  // type of camera (public)
  public final static int LEFT_EYE = 0;
  public final static int RIGHT_EYE = 1;

  // camera frustum constants
  private static final double IOD = 0.2;
  // intraocular distance (eye separation distance)
  private static final double FOVY = 45.0;
  private static final double NEAR_DIST = 1.0;
  private static final double SCREEN_DIST = 5.0;
  private static final double FAR_DIST = 100.0;


  // OpenGL
  private GL gl;
  private GLU glu;

  private int eyeType;    // eye info

  // viewport dimensions
  private int xVP, yVP, widthVP, heightVP;

  // frustum info
  private double top, bottom, left, right;
  private double frustumShift;



  public EyeCamera(GL gl, GLU glu, int eType)
  {
    this.gl = gl;
    this.glu = glu;

    eyeType = eType;

    frustumShift = (IOD/2.0) * NEAR_DIST/SCREEN_DIST;

    top = NEAR_DIST * Math.tan((FOVY/2.0*Math.PI)/360.0);
    bottom = -top;
  } // end of EyeCamera()




  public void updateViewVals(int x, int y, int w, int h)
  // update the viewport and frustum dimensions
  {
    // update viewport coordinates
    xVP = x; yVP = y;

    widthVP = w;
    if (h == 0)
      h = 1;
    heightVP = h;

    double aspectRatio = (double)widthVP/(double)heightVP;

    // calculate left and right near clipping plane dimensions
    left = bottom * aspectRatio;
    right = top * aspectRatio;

    // modify left and right to specify an asymmetric frustum
    if (eyeType == LEFT_EYE) {
      left += frustumShift;    // shift left eye frustum to the right
      right += frustumShift;
    }
    else {  // right eye
      left -= frustumShift;    // shift right eye frustum to the left
      right -= frustumShift;
    }
  }  // end of updateViewVals()



  public void set(double xPlayer, double yPlayer, double zPlayer,
                  double xLookAt, double yLookAt, double zLookAt)
  /* Set the viewport, perspective projection frustum for this
     camera, and its position. */
  {
    gl.glViewport(xVP, yVP, widthVP, heightVP);

    gl.glMatrixMode(GL.GL_PROJECTION);  // set the view attributes
    gl.glLoadIdentity();

    gl.glFrustum(left, right, bottom, top, NEAR_DIST, FAR_DIST);
             // specifies an asymmetric frustum view volume


    gl.glMatrixMode(GL.GL_MODELVIEW);
    gl.glLoadIdentity();

    // adjust for x-axis eye offset
    double xEye;
    if (eyeType == LEFT_EYE)
      xEye = xPlayer - IOD/2.0;  // shift left eye to the left
    else  // right eye
      xEye = xPlayer + IOD/2.0;  // shift right eye to the right

    glu.gluLookAt(xEye, yPlayer, zPlayer,
                  xLookAt, yLookAt, zLookAt, 0,1,0);    // position camera
  } // end of set()


}  // end of EyeCamera class